package study.spring.core.ioc._2_inject_bean;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class AtBeanMethodInvokeAtBeanMethod {
  /**
   * 使用 @Bean 注解的处理过程, 以及 在另外的使用@Bean注解的方法 中调用本方法
   */
  @Bean("atBeanAnnotation")
  public AtBeanAnnotationBean beInvokedMethod() {
    return new AtBeanAnnotationBean();
  }

  /**
   * {@link org.springframework.context.annotation.ConfigurationClassEnhancer#enhance(Class, ClassLoader)}
   * 极其重要的 BeanMethodInterceptor 拦截器
   * {@link org.springframework.context.annotation.ConfigurationClassEnhancer.BeanMethodInterceptor }
   *
   * {@link org.springframework.context.annotation.ConfigurationClassEnhancer.BeanMethodInterceptor#resolveBeanReference }
   */
  @Bean("atBeanAnnotationTwo")
  public AtBeanAnnotationBeanTwo testProxyEnhanceEffect() {
    /* 有 @Configuration注解
              使用 @Bean注解的方法, 会被 spring 增强为代理方法, 如这里的 beInvokedMethod() 方法,
              在 testProxyEnhanceEffect 中调用, 最终会执行 代理后的 beInvokedMethod() 方法,
              在这个 代理方法中: 有这样一个判断
                   if (isCurrentlyInvokedFactoryMethod(beanMethod))
              因为当前方法是 testProxyEnhanceEffect 方法, 调用的是 beInvokedMethod 方法, 所以这里并不相等,
              最终不执行 cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs) 方法,
                   也就是不执行 被代理前的 beInvokedMethod 方法,
              而去执行 resolveBeanReference 方法, 使用 beanFactory 执行 getBean 方法获取 bean

        没有 @Configuration注解
              使用@Bean注解的方法, 不会被 spring 增强为代理方法
              在这里调用, 会执行 原始的 beInvokedMethod 方法

        从 spring 5.2 开始, 可是使用 @Configuration(proxyBeanMethods = false) 关闭                      */
    beInvokedMethod();
    return new AtBeanAnnotationBeanTwo();
  }
}
